package cn.cas.mango.service;
import cn.cas.mango.dbscan.DBSCAN;
import cn.cas.mango.dbscan.Data;
import cn.cas.mango.dto.param.HitNews;
import cn.cas.mango.dto.param.News;
import co.elastic.clients.elasticsearch._types.SortOrder;

import lombok.extern.slf4j.Slf4j;

import java.util.*;

@Slf4j
public class SameNewsService {
  private final Map<String, HitNews> cast = new HashMap<>();
  private Map<String, Map<String, Double>> map2Score;
  private final SortOrder sortOrder;
  private final String sortField;

  private final Integer range;
  private final List<HitNews> hits;
  public SameNewsService(List<HitNews> hits, SortOrder order, String sortField, Integer range) {
    this.hits = hits;
    this.sortOrder = order;
    this.sortField = sortField;
    this.range = range;
  }
  private void generateCast()  {
    for (HitNews hit: hits) {
      cast.put(hit.getId(), hit);
    }
  }

  private Map<String, List<String>> runDBSCAN(List<HitNews> hits, double factor, Integer range,
                                              Map<String, Set<String>> clusterKeywordMap ) {
    List<Data> rawAllData = new ArrayList<>();
    for (HitNews hit1: hits) {
      rawAllData.add(wrappedData(hit1));
    }
    try {
      DBSCAN dbscan = new DBSCAN(rawAllData, range, clusterKeywordMap);
      Map<String, List<String>> run = dbscan.run(factor);
      map2Score = dbscan.getMap2Score();
      return run;
    } catch (Exception e) {
      e.printStackTrace();
    }
    map2Score = new HashMap<>();
    return new HashMap<>();
  }

  public Map<String, Map<String, Double>> getMap2Score() {
    return map2Score;
  }

  private Data wrappedData(HitNews hit) {
    String id = hit.getId();
    News news = hit;
    Double score = hit.getScore();
    Set<String> keywords = new HashSet<>();
    try {
      assert news != null;
      if (news.getNewsKeywords() != null) {
        Object key = news.getNewsKeywords();
        if (key instanceof List) {
          keywords.addAll((List)key);
        } else {

          keywords.add((String) key);
        }
      }

    } catch (Exception e) {
      e.printStackTrace();
    }

    // 如果新闻时间空缺，指定一个默认时间
    String date = "2010-02-02";
    if (news.getNewsPublicTime() != null) {

      date = news.getNewsPublicTime();
    }
    return new Data(id, keywords, date, score, sortOrder, sortField);
  }
  public Map<String, Map<String, Object>> getSameNewsList(double factor) {
    generateCast();
    Map<String, Set<String>> clusterKeywordMap = new HashMap<>();
    Map<String, List<String>> map = runDBSCAN(hits, factor, range, clusterKeywordMap);
    Map<String, Map<String, Object>> ret = new LinkedHashMap<>();
    for (String key: map.keySet()) {
      Map<String, Object> inner = new LinkedHashMap<>();

      ret.put(key, inner);
      List<HitNews> likeList = new ArrayList<>();
      for (String string: map.get(key)) {
        likeList.add(cast.get(string));
      }
      inner.put("like", likeList);
      ret.get(key).put("cluster_keywords", clusterKeywordMap.get(key));
      ret.get(key).put("self", cast.get(key));
    }
    return ret;
  }
}
